/*
 * RemoteServer.java   0.0.1    28/set/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */
package org.mentalsmash.tazio.net.cs.client;

import java.io.IOException;
import java.net.InetAddress;

/**
 * Represents a Remote Server.
 * <p>
 * A <tt>RemoteServer</tt> instance can be in one of two states at any time:
 * <ul>
 * <li>
 * <strong>Connected State</strong>: if an actual connection (e.g. a socket
 * connection) with the remote server is established. <br/>
 * When in this state interactions with the server can be performed using the
 * {@link Connection} instance retrievable with
 * {@link RemoteServer#getConnection()}.</li>
 * <li>
 * <strong>Disconnected State</strong>: if there is no actual connection to a
 * remote server. <br />
 * When in this state you can call {@link #connect(InetAddress,int)} to try to
 * establish a connection.</li>
 * </ul>
 * </p>
 * 
 * @author Andrea Reale <andrea.reale@gmail.com
 * @version 0.0.1
 * @see Connection
 */
public interface RemoteServer {
    /**
     * Connects to a server that is listening at the address specified by the
     * <code>address</code> parameter, and returns a reference to a
     * {@link Connection} instance to permit interacting with that server.
     * <p>
     * If this instance is already in the <i>Connected State</i> this method
     * behaves exactly like {@link #getConnection()}.
     * </p>
     * <p>
     * Once the connection is established this method changes the internal state
     * of the <tt>RemoteServer</tt> instance to reflect the current address and
     * port to wich it is connected
     * </p>
     * 
     * @param address
     *            an Internet Address locating the desired server
     * @param port
     *            the port to connect to
     * @return a reference to the {@link Connection} instance associated with
     *         the established connection
     */
    Connection connect(InetAddress address, int port) throws IOException;

    /**
     * Connects to a server that is listening at the address of this
     * <tt>RemoteServer</tt>, and returns a reference to a {@link Connection}
     * instance to permit interacting with that server.
     * <p>
     * If this instance is already in the <i>Connected State</i> this method
     * behaves exactly like {@link #getConnection()}.
     * </p>
     * 
     * @return a reference to the {@link Connection} instance associated with
     *         the established connection
     */
    Connection connect() throws IOException;
    
    Connection connect(boolean useGzip) throws IOException;

    /**
     * If a connection with a remote server is currently established,
     * disconnects it and frees the underlying resource. <br />
     * If no connection to the server is established, it does nothing.
     */
    void disconnect();

    /**
     * If in the <i>Connected State</i> returns the associated
     * {@link Connection} instance.
     * <p>
     * If there is no actual connection with the RemoteServer returns
     * <code>null</code>
     * </p>
     * 
     * @return the connection to the remote server, or <code>null</code> if
     *         there's no connection
     */
    Connection getConnection();

    /**
     * Returns the address currently associated with this <tt>RemoteServer</tt>.
     * <p>
     * If this instance is in the <i>Connected State</i> this address also
     * reflects the actual address where the server is listening.
     * </p>
     * <p>
     * If in the <i>Disconnected State</i> this address may or may not reflect
     * the real address where the server is listening.
     * </p>
     * 
     * @return the address currently associated with this <tt>RemoteServer</tt>.
     */
    InetAddress getAddress();

    /**
     * Sets the address associated with this instance of <tt>RemoteSever</tt>.
     * <p>
     * This method should be called only when the instance is in the
     * <i>Disconnected State</i>. <br/>
     * If it is called while in the <i>Connected State</i> it throws a
     * {@link ConnectionStateExeption}
     * </p>
     * 
     * @param address
     *            the address where the server is listening
     * @throws ConnectionStateException
     *             if this method is called while in the <i>Connected State</i>
     */
    void setAddress(InetAddress address) throws ConnectionStateExeption;

    /**
     * Checks whether the instance of Remote Server is connected to an actual
     * server
     * 
     * @return <code>true</code> if the instance is connected and ready to
     *         accept messages
     */
    boolean isConnected();

}
